#!/bin/sh

die () {
  echo "ERROR: $1" >&2
  exit 1
}

REPO=head.hackage.ghc.haskell.org

cat_repo () {
cat <<EOF
repository $REPO
   url: http://ghc.gitlab.haskell.org/head.hackage/
   secure: True
   root-keys: 7541f32a4ccca4f97aea3b22f5e593ba2c0267546016b992dfadcd2fe944e55d
              26021a13b401500c8eb2761ca95c61f2d625bfef951b939a8124ed12ecf07329
              f76d08be13e9a61a377a85e2fb63f4c5435d40f8feb3e12eb05905edb8cdea89
   key-threshold: 3

EOF
}

# this needs to match the `remote-repo-cache` global config setting
PKGCACHE="${HOME}/.cabal/packages"

check_pkgcache () {
  mkdir -p $PKGCACHE
  if [ ! -d "$PKGCACHE" ]; then
    die "package cache folder ('$PKGCACHE') doesn't seem exist; please edit script"
  fi
}

# CABAL executable
# If $CABAL env-var is set, use that; otherwise default to the executable 'cabal'
CABAL=${CABAL:-cabal}

# GHC handling
check_ghc () {
  if [ -z "$GHC" -a -x "/opt/ghc/head/bin/ghc" ]; then
    echo "INFO: \$GHC was unset. Using the detected '/opt/ghc/head/bin/ghc' executable!"
    echo "      Set \$GHC to a different compiler if needed or edit the generated"
    echo "      'cabal.project(.local)' file accordingly"
    echo ""
    GHC="/opt/ghc/head/bin/ghc"
  fi

  # set $GHC to the name or (or full path if not in $PATH) of the GHC HEAD executable
  if [ -z "$GHC" ]; then
    die "set \$GHC with the path to your GHC HEAD executable"
  elif [ ! -f "$GHC" -a ! -x "$GHC" ]; then
    echo "WARNING: \$GHC='$GHC' does not appear to be a GHC executable"
  fi
}

############################################################################
# main

case "X$1" in
  Xupdate)
    check_pkgcache

    if "$CABAL" new-update --help > /dev/null 2>&1; then
      echo "INFO: '$CABAL' is recent enough and supports 'cabal new-update $REPO'; you can try using that directly!"
      echo ""

      CFGFILE=$(mktemp)
      cat_repo > "$CFGFILE"

      # we need to wipe the cache for head.hackage to workaround issues in hackage-security
      rm -rf "$PKGCACHE/$REPO/"

      echo "http-transport: plain-http" >> "$CFGFILE"

      "$CABAL" --project-file="$CFGFILE" new-update $REPO

      rm "$CFGFILE"
    else
      echo "INFO: '$CABAL' doesn't seem to support 'cabal new-update' yet. Using legacy fallback"

      CFGFILE=$(mktemp)
      cat_repo > "$CFGFILE"

      # we need to wipe the cache for head.hackage to workaround issues in hackage-security
      rm -rf "$PKGCACHE/$REPO/"

      echo "http-transport: plain-http" >> "$CFGFILE"
      echo "remote-repo-cache: $PKGCACHE" >> "$CFGFILE"

      "$CABAL" --config-file="$CFGFILE" update

      rm "$CFGFILE"
    fi
    ;;

  Xdump-repo)
    cat_repo
    ;;

  Xinit)
    if [ -e cabal.project ]; then
      die "cabal.project file exists already, aborting! Use '$0 init-local' to generate a 'cabal.project.local' config."
    else
      check_ghc

      echo "INFO: creating new cabal.project file"

      {
        cat <<EOF
-- generated by head.hackage.sh

with-compiler: $GHC

EOF
        echo "packages: ."
        shift
        for PKG in "$@"; do
          echo "optional-packages: $PKG"
        done

        echo ""
        cat_repo

        echo "-- end of generated content"
      } > cabal.project

    fi

    ;;


  Xinit-local)
    if [ ! -e cabal.project ]; then
      die "cabal.project does not exist, aborting!"
      exit 1
    fi

    if [ -e cabal.project.local ]; then
      die "cabal.project.local file exists already, aborting!"
    else
      check_ghc

      echo "INFO: creating new cabal.project.local file"

      {
        cat <<EOF
-- generated by head.hackage.sh

with-compiler: $GHC

EOF
        shift
        for PKG in "$@"; do
          echo "optional-packages: $PKG"
        done

        echo ""
        cat_repo

        echo "-- end of generated content"
      } > cabal.project.local

    fi

    ;;


  Xhelp)
    cat <<EOF
Usage: $0 <command>

Known <commands>

 update             update head.hackage package index

 init [folder(s)]   create cabal.project file for GHC HEAD and
                    optionally populate 'packages:' with extra folders

 init-local [folder(s)] create 'cabal.project.local' file for GHC HEAD
                    and optionally populate 'packages:' with extra folders

 dump-repo          dump 'repository' declaration to stdout and exit

 help               show help (you're here)

EOF
    ;;

  X)
    echo "no command given; try 'help'" >&2
    exit 1
    ;;

  *)
    die "unrecognised command '$1'; try 'help'"
    ;;
esac


# Local variables:
# coding: utf-8
# mode: sh
# sh-basic-offset: 2
# sh-indentation: 2
# End:

